package edu.cicese.alz;

import edu.cicese.alz.reports.NFCProfile;
import edu.cicese.alz.reports.NFCTag;
import edu.cicese.alz.swing.CustomButton;
import edu.cicese.alz.swing.CustomComboBoxRenderer;
import edu.cicese.alz.swing.JColorButton;
import edu.cicese.alz.swing.JNonEmptyTextField;
import edu.cicese.alz.swing.PropertyNameDocumentFilter;
import edu.cicese.alz.swing.ScrollablePane;
import edu.cicese.alz.swing.SwingUtil;
import edu.cicese.alz.swing.dialogs.ConfirmationDialog;
import edu.cicese.alz.swing.dialogs.ErrorDialog;
import edu.cicese.alz.util.PropertyUtil;

import javax.swing.Box;
import javax.swing.Icon;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.AbstractDocument;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.TreeSet;

/**
 * Created by: Eduardo Quintana Contreras
 * Date: 23/07/12
 * Time: 09:14 PM
 */
public class PaneNFCTags extends ScrollablePane {

	private FrameNFCTags frmNFCTags;

	private Box boxNFCTags;

	private JPanel pTags, pProfileTags;
	private JComboBox cmbProfiles;

	private ArrayList<NFCTag> tags = new ArrayList<>();
	private JNonEmptyTextField txtNewTagName;
	private JColorButton btnNewTagColor;

	private Icon iconProfiled, iconNotProfiled;

//	private ArrayList<NFCProfile> nfcProfiles = new ArrayList<>();
	private JNonEmptyTextField txtProfileName;
	private CustomButton btnDeleteProfile;

	public PaneNFCTags(FrameNFCTags frmNFCTags) {
		this.frmNFCTags = frmNFCTags;
		initComponents();
		initScrollablePane(boxNFCTags, Color.WHITE);
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				load();
				reloadTags();
				enableButtons(false);
//				loadProfiles();
//				loadTags();
			}
		});
	}


	public void initComponents() {
		// Tags
		CustomButton btnNewNfcTag = SwingUtil.createCustomButton("", "New NFC tag", getIcon("b_new"), Color.WHITE);
		btnNewNfcTag.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				actionNewTag();
			}
		});

		CustomButton btnDeleteNfcTag = SwingUtil.createCustomButton("", "Delete selected NFC tag(s)", getIcon("b_delete"), Color.WHITE);
		btnDeleteNfcTag.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				actionDeleteTag();
			}
		});

		CustomButton btnSelectTags = SwingUtil.createCustomButton("", "Select all tags", getIcon("b_select_all"), Color.WHITE);
		btnSelectTags.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				actionSelectTags(true);
			}
		});

		CustomButton btnDeselectTags = SwingUtil.createCustomButton("", "Deselect all tags", getIcon("b_select_none"), Color.WHITE);
		btnDeselectTags.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				actionSelectTags(false);
			}
		});

		CustomButton btnReloadFromDatabase = SwingUtil.createCustomButton("", "Reload from database", getIcon("b_reload_db"), Color.WHITE);
		btnReloadFromDatabase.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				reloadFromDatabase();
			}
		});

		Box boxTagButtons = createHorizontalBox(new Component[]{
				btnDeleteNfcTag, btnSelectTags, btnDeselectTags, btnReloadFromDatabase
		});

		txtNewTagName = SwingUtil.createNonEmptyTextField(200, 20);
		txtNewTagName.getDocument().addDocumentListener(new EmptyTextListener(txtNewTagName));
		((AbstractDocument) txtNewTagName.getDocument()).setDocumentFilter(new PropertyNameDocumentFilter(txtNewTagName));
		btnNewTagColor = SwingUtil.createColorButton(20, 20);

		Box boxNewTag = createHorizontalBox(new Component[]{
				new JLabel("NFC tag string:"),
				Box.createHorizontalStrut(4),
				txtNewTagName,
				Box.createHorizontalStrut(4),
				btnNewTagColor,
				Box.createHorizontalStrut(4),
				btnNewNfcTag
		});

		pTags = createEmptyPane();

		Box boxTags = createVerticalBox(new Component[]{
				boxTagButtons,
				boxNewTag,
				pTags
		});

		// Profiles
		CustomButton btnNewProfile = SwingUtil.createCustomButton("", "New profile", getIcon("b_new"), Color.WHITE);
		btnNewProfile.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				actionNewProfile();
			}
		});

		btnDeleteProfile = SwingUtil.createCustomButton("", "Delete profile", getIcon("b_delete"), Color.WHITE);
		btnDeleteProfile.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				actionDeleteProfile();
			}
		});

		CustomButton btnSelectProfileTags = SwingUtil.createCustomButton("", "Select all profile tags", getIcon("b_select_all"), Color.WHITE);
		btnSelectProfileTags.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				actionSelectProfileTags(true);
			}
		});

		CustomButton btnDeselectProfileTags = SwingUtil.createCustomButton("", "Deselect all profile tags", getIcon("b_select_none"), Color.WHITE);
		btnDeselectProfileTags.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				actionSelectProfileTags(false);
			}
		});

		CustomButton btnDeleteProfileTag = SwingUtil.createCustomButton("", "Delete tag from profile", getIcon("b_up"), Color.WHITE);
		btnDeleteProfileTag.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				actionDeleteProfileTag();
			}
		});

		CustomButton btnAddProfileTag = SwingUtil.createCustomButton("", "Add tag to profile", getIcon("b_down"), Color.WHITE);
		btnAddProfileTag.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				actionAddProfileTag();
			}
		});


		Box boxProfileButtons = createHorizontalBox(new Component[]{
				btnAddProfileTag, btnDeleteProfileTag, btnSelectProfileTags, btnDeselectProfileTags
		});

		cmbProfiles = SwingUtil.createComboBox(new String[]{}, 125, 20);
//		cmbProfiles.setModel(new CustomComboBoxModel(nfcProfiles));
		cmbProfiles.setRenderer(new CustomComboBoxRenderer());
		cmbProfiles.addActionListener(new ProfileActionListener());
		txtProfileName = SwingUtil.createNonEmptyTextField(120, 20);
		txtProfileName.getDocument().addDocumentListener(new EmptyTextListener(txtProfileName));
		txtProfileName.getDocument().addDocumentListener(new ProfileChangeListener(txtProfileName));
		((AbstractDocument) txtProfileName.getDocument()).setDocumentFilter(new PropertyNameDocumentFilter(txtProfileName));

		Box boxProfileName = createHorizontalBox(new Component[]{
				new JLabel("Profile name:"),
				Box.createHorizontalStrut(4),
				txtProfileName,
				Box.createHorizontalStrut(4),
				btnNewProfile,
				Box.createHorizontalStrut(4),
				cmbProfiles,
				Box.createHorizontalStrut(4),
				btnDeleteProfile
		});

		pProfileTags = createEmptyPane();

		Box boxProfiles = createVerticalBox(new Component[]{
				boxProfileButtons,
				boxProfileName,
				Box.createVerticalStrut(4),
				pProfileTags
		});

		boxNFCTags = createVerticalBox(new Component[]{
				createTitlePane("NFC Tags"),
				Box.createVerticalStrut(4),
				boxTags,
				Box.createVerticalStrut(4),
				createTitlePane("Profiles"),
				Box.createVerticalStrut(4),
				boxProfiles
		});

		iconProfiled = getIcon("b_profiled");
		iconNotProfiled = getIcon("b_not_profiled");

		btnDeleteProfile.setEnabled(false);
	}


	public void actionSaveChanges(boolean okd) {
		if (!tagError()) {
			if (showSaveDialog()) {
				saveChanges();
				if (okd) {
					close();
				}
			}
		} else {
			new ErrorDialog(this, "Invalid input", "Please set a valid tag name for the marked NFC tag(s).");
		}
	}

	public void actionCancelChanges() {
		ConfirmationDialog dialog = new ConfirmationDialog(this,
				"Confirmation dialog",
				"Changes will be lost. Continue?");
		if (dialog.isOk()) {
			load();
			reloadTags();
//			showProfileTags();

			enableButtons(false);

			// close window
			close();
		}
		dialog.dispose();
	}

	private void actionSelectTags(boolean select) {
		for (NFCTag nfcTag : tags) {
			nfcTag.getTagCheckBox().setSelected(select);
		}
	}

	private boolean showSaveDialog() {
		ConfirmationDialog dialog = new ConfirmationDialog(this,
				"Confirmation dialog",
				"Changes will be saved permanently. Continue?");
		boolean value = dialog.isOk();
		dialog.dispose();
		return value;
	}

	private void saveChanges() {
		// Save nfc tags
		String value = "";
		for (NFCTag nfcTag : tags) {
			String tagName = nfcTag.getText().trim();
			value += tagName + "," + String.valueOf(nfcTag.getColor().getRGB()) + ";";
		}
		PropertyUtil.setProperty(PropertyUtil.NFC_TAGS, value);

		String profiles = "";
		for (int i = 0; i < cmbProfiles.getItemCount(); i++) {
			NFCProfile profile = (NFCProfile) cmbProfiles.getItemAt(i);

			// store profile name
			profiles += profile.getNewProfileName() + ";";

			// store profile values ("tag name", "tag color")
			value = "";
			for (NFCTag tag : profile.getTags()) {
				value += tag.getText() + "," + String.valueOf(tag.getProfileColor(profile).getRGB()) + ";";
			}

			// delete old profile
			PropertyUtil.removeNFCProfile(getProfilePropertyName(profile.getProfileName()));

			// save new profile
			PropertyUtil.setProperty("NFC_PROFILE_" + profile.getNewProfileName(), value);
		}
		// save profile names
		PropertyUtil.setProperty(PropertyUtil.NFC_PROFILES, profiles);

		// disable save and cancel buttons
		enableButtons(false);
	}

	public void close() {
		if (frmNFCTags.isModal()) {
			frmNFCTags.reloadProfiles();
		}
		frmNFCTags.closeWindow(true);
	}


	// Tags
	private void actionNewTag() {
		String text = txtNewTagName.getText().trim();
		if (!text.equals("")) {

			if (!exists(text, tags)) {
				addTag(text, btnNewTagColor.getBackground());
				reloadTags();

				enableButtons(true);
			} else {
				new ErrorDialog(this, "Duplicated tag", "The NFC tag name \"" + text + "\" already exists.");
//				System.out.println("Tag already exists.");
			}
		} else {
			new ErrorDialog(this, "Invalid input", "Please specify a valid NFC tag name.");
//			System.out.println("Please specify a valid tag name.");
		}

		txtNewTagName.requestFocus();
	}

	private void actionDeleteTag() {
		ConfirmationDialog dialog = new ConfirmationDialog(this,
				"Confirmation dialog",
				"This action will also delete the NFC tag(s) selected from the profiles. Continue?");
		if (dialog.isOk()) {
			boolean removed = false;
			for (int i = tags.size() - 1; i >= 0; i--) {
				if (tags.get(i).isSelected()) {
					// remove from profiles
					removeFromProfiles(tags.get(i).getText().trim());
					tags.remove(i);

					removed = true;
				}
			}

			if (removed) {
				reloadTags();
				enableButtons(true);
			}

		}
	}


	// Profile
	private void actionNewProfile() {
		String text = txtProfileName.getText().trim();
		if (!text.equals("")) {
			if (!existsInProfiles(text, true)) {
				// revert profile name changes
				if (cmbProfiles.getItemCount() > 0) {
					getSelectedProfile().setNewProfileName(getSelectedProfile().getProfileName());
				}

				NFCProfile nfcProfile = new NFCProfile(text, text, true);

//				((CustomComboBoxModel) cmbProfiles.getModel()).addElement(nfcProfile);
				cmbProfiles.addItem(nfcProfile);

				cmbProfiles.setSelectedItem(nfcProfile);
			} else {
				new ErrorDialog(this, "Duplicated profile", "The NFC profile name \"" + text + "\" already exists.");
//				System.out.println("Profile already exists.");
			}
		} else {
			new ErrorDialog(this, "Invalid input", "Please specify a valid NFC profile name.");
//			System.out.println("Please specify a valid profile name.");
		}
	}

	private void actionDeleteProfile() {
		ConfirmationDialog dialog = new ConfirmationDialog(this,
				"Confirmation dialog",
				"Are you sure you want to delete the profile \"" + getSelectedProfile().getNewProfileName() + "\"?");
		if (dialog.isOk()) {
			int selectedIndex = cmbProfiles.getSelectedIndex();
//			((CustomComboBoxModel) cmbProfiles.getModel()).removeElement(getSelectedProfile());
			cmbProfiles.removeItem(getSelectedProfile());

			int itemCount = cmbProfiles.getItemCount();

			if (selectedIndex <= itemCount - 1) {
				cmbProfiles.setSelectedIndex(selectedIndex);
			}
			else {
				cmbProfiles.setSelectedIndex(selectedIndex - 1);
			}
			showProfileTags();

			enableButtons(true);
		}
		dialog.dispose();
	}

	private void actionAddProfileTag() {
		if (!tagError()) {
			if (cmbProfiles.getItemCount() != -1) {
				boolean added = false;
				for (NFCTag nfcTag : tags) {
					if (nfcTag.isSelected() && !nfcTag.isProfiled()) {
						nfcTag.setProfiled(true, iconProfiled);

						// add to profile
						addProfileTag(nfcTag);

						added = true;
					}
					nfcTag.setSelected(false);
				}

				if (added) {
					showProfileTags();
					enableButtons(true);
				}
			}
			else {
				new ErrorDialog(this, "Error", "Please create a new profile first.");
			}
		} else {
			new ErrorDialog(this, "Invalid input", "Please set a valid tag name for the marked NFC tag(s).");
//			System.out.println("Please set a valid tag name for the marked NFC tag(s).");
		}
	}

	private void actionDeleteProfileTag() {
		ConfirmationDialog dialog = new ConfirmationDialog(this,
				"Confirmation dialog",
				"Are you sure you want to delete the selected NFC tag(s) from the profile?");
		if (dialog.isOk()) {
			ArrayList<NFCTag> profileTags = getProfileTags();

			boolean removed = false;

			for (int i = profileTags.size() - 1; i >= 0; i--) {
				NFCTag profileTag = getProfileTags().get(i);

				if (profileTag.getProfileCheckBox().isSelected()) {
					profileTag.setProfiled(false, iconNotProfiled);
					profileTags.remove(profileTag);

					removed = true;
				}
			}

			if(removed) {
				showProfileTags();
				enableButtons(true);
			}
		}
		dialog.dispose();
	}

	private void actionSelectProfileTags(boolean select) {
		for (NFCTag nfcTag : getProfileTags()) {
			nfcTag.getProfileCheckBox().setSelected(select);
		}
	}


	private void load() {
		// Create NFCTags
		String nfcTags = PropertyUtil.getProperty(PropertyUtil.NFC_TAGS);
		tags.clear();

		if (!nfcTags.equals("")) {
			try {
				String[] colors = nfcTags.split(";");

				for (String color : colors) {
					String[] values = color.split(",");
					tags.add(createTag(values[0], new Color(Integer.valueOf(values[1]))));
				}
			} catch (NullPointerException ex) {
				ex.printStackTrace();
			}
		}

		// Load profiles and update NFCTags
//		nfcProfiles.clear();

//		cmbProfiles.setModel(new CustomComboBoxModel(nfcProfiles));
		cmbProfiles.removeAllItems();
//		cmbProfiles.configureEditor(cmbProfiles.getEditor(), null);
		cmbProfiles.getEditor().setItem(null);
//		cmbProfiles.revalidate();
//		cmbProfiles.repaint();
		cmbProfiles.setSelectedIndex(-1);

		String profileString = PropertyUtil.getProperty(PropertyUtil.NFC_PROFILES);
		if (!profileString.equals("")) {
			String[] profiles = profileString.split(";");
			for (String profileName : profiles) {
				NFCProfile nfcProfile = new NFCProfile(profileName, profileName, false);
//				((CustomComboBoxModel) cmbProfiles.getModel()).addElement(nfcProfile);
				cmbProfiles.addItem(nfcProfile);

				loadProfileTags(nfcProfile);
			}
			cmbProfiles.setSelectedIndex(0);
		}
//		txtNewTagName.setText("");
//		txtProfileName.setText("");
	}

	public void reloadFromDatabase() {
		try {
			ResultSet resultSet = Query.executeQuery(Query.queryNFCData());
			if (resultSet != null) {
				while (resultSet.next()) {
					String message = resultSet.getString(1);
					if (!exists(message, tags)) {
						tags.add(createTag(message, Color.BLACK));
					}
				}
				reloadTags();
				showProfileTags();
			}
			else {
				new ErrorDialog(this, "Database error", "Couldn't connect to database.");
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			Query.close();
		}
	}

	public static void reloadFromDatabaseAndSave() {
		TreeSet<String> tagNames = new TreeSet<>();
		ArrayList<NFCTag> tags = new ArrayList<>();
		String nfcTags = PropertyUtil.getProperty(PropertyUtil.NFC_TAGS);

		if (!nfcTags.equals("")) {
			try {
				String[] colors = nfcTags.split(";");
				for (String color : colors) {
					String[] values = color.split(",");
					tags.add(new NFCTag(values[0], new Color(Integer.valueOf(values[1]))));
					tagNames.add(values[0]);
				}
			} catch (NullPointerException ex) {
				ex.printStackTrace();
			}
		}

		try {
			boolean added = false;
			ResultSet resultSet = Query.executeQuery(Query.queryNFCData());
			while (resultSet.next()) {
				String message = resultSet.getString(1);
				if (!tagNames.contains(message)) {
					tags.add(new NFCTag(message, Color.BLACK));
					added = true;
				}
			}
			if (added) {
				String value = "";
				for (NFCTag nfcTag : tags) {
					String tagName = nfcTag.getText().trim();
					value += tagName + "," + String.valueOf(nfcTag.getColor().getRGB()) + ";";
				}
				PropertyUtil.setProperty(PropertyUtil.NFC_TAGS, value);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			Query.close();
		}
	}


	private void reloadTags() {
		if (tags.size() > 0) {
			addTagsToPane();
		} else {
			empty(pTags);
		}
	}

	private void addTagsToPane() {
		int tagRowSize = 12;
		Box[] boxes = new Box[(int) Math.ceil((double) tags.size() / tagRowSize)];

		for (int b = 0, c = 0; b < boxes.length; b++) {
			boxes[b] = Box.createVerticalBox();
			if (b != 0) {
				setBoxLeftBorder(boxes[b], 20);
			}

			for (int i = c; i < c + tagRowSize && i < tags.size(); i++) {
				NFCTag nfcTag = tags.get(i);
				Box boxTag = createHorizontalBox(new Component[]{
						nfcTag.getLabel(),
						Box.createHorizontalStrut(3),
						nfcTag.getTagCheckBox(),
						Box.createHorizontalStrut(3),
						nfcTag.getTextField(),
						Box.createHorizontalStrut(4),
						nfcTag.getTagButton()
				});
				boxes[b].add(Box.createVerticalStrut(2));
				boxes[b].add(boxTag);
			}
			c += tagRowSize;
		}

		pTags.removeAll();
		setPaneContent(pTags, boxes);

		int width, height;

		// set tags' panel width
		// JLabel's width = 12
		// space = 3
		// JCheckBox's width = 14
		// space = 3
		// JNonEmptyTextField's width = 200
		// space = 4
		// JColorButton's width = 20
		// = 256
		width = boxes.length * 256 + (boxes.length - 1) * 20;

		// set tags' panel height
		if (tags.size() >= tagRowSize) {
			height = tagRowSize * 22;
		} else {
			height = tags.size() * 22;
		}
		pTags.setPreferredSize(new Dimension(width, height));
		pTags.setMinimumSize(pTags.getPreferredSize());
		pTags.setMaximumSize(pTags.getPreferredSize());

//		pTags.revalidate();
//		pTags.repaint();
	}

	private void addTag(String tagName, Color tagColor) {
		NFCTag nfcTag = createTag(tagName, tagColor);
		if (exists(tagName, getProfileTags())) {
			nfcTag.setProfiled(true, iconProfiled);
		} else {
			nfcTag.setProfiled(false, iconNotProfiled);
		}
		tags.add(nfcTag);
	}

	private NFCTag createTag(String tagName, Color tagColor) {
		JNonEmptyTextField textField = SwingUtil.createNonEmptyTextField(200, 20);
		textField.getDocument().addDocumentListener(new DuplicateTagListener());
		((AbstractDocument) textField.getDocument()).setDocumentFilter(new PropertyNameDocumentFilter(textField));
		textField.setText(tagName);

		return new NFCTag(new JLabel(), SwingUtil.createCheckBox(""), textField, SwingUtil.createColorButton(20, 20, tagColor));
	}


	private void showProfileTags() {
		if (getProfileTags().size() > 0) {
			addProfileTagsToPane();
		} else {
			empty(pProfileTags);
		}

		revalidate();
		repaint();

		for (NFCTag nfcTag : tags) {
			if (getProfileTags().size() > 0 && getProfileTags().contains(nfcTag)) {
				nfcTag.setProfiled(true, iconProfiled);
			} else {
				nfcTag.setProfiled(false, iconNotProfiled);
			}
		}
	}

	private void loadProfileTags(NFCProfile nfcProfile) {
		String profileProperty = PropertyUtil.getProperty(getProfilePropertyName(nfcProfile.getProfileName()));
		ArrayList<NFCTag> nfcTags = nfcProfile.getTags();

		if (!profileProperty.equals("")) {
			try {
				String[] colors = profileProperty.split(";");

				if (colors.length > 0) {
					for (String color : colors) {
						String[] values = color.split(",");

						for (NFCTag nfcTag : tags) {
							if (nfcTag.getText().equals(values[0])) {
								nfcTag.addToProfile(nfcProfile, new Color(Integer.valueOf(values[1])));
								nfcTags.add(nfcTag);
								break;
							}
						}
					}
				}
			} catch (NullPointerException ex) {
				ex.printStackTrace();
				nfcTags.clear();
			}
		}
	}

	private void addProfileTagsToPane() {
		ArrayList<NFCTag> profileTags = getProfileTags();
		int tagRowSize = 8;
		Box[] boxes = new Box[(int) Math.ceil((double) profileTags.size() / tagRowSize)];

		for (int b = 0, c = 0; b < boxes.length; b++) {
			boxes[b] = Box.createVerticalBox();
			if (b != 0) {
				setBoxLeftBorder(boxes[b], 20);
			}

			for (int i = c; i < c + tagRowSize && i < profileTags.size(); i++) {
				Box boxTag = createHorizontalBox(new Component[]{
						profileTags.get(i).getProfileCheckBox(),
						Box.createHorizontalStrut(3),
						profileTags.get(i).getProfileButton(getSelectedProfile()),
				});
				boxes[b].add(boxTag);
				boxes[b].add(Box.createVerticalStrut(2));
			}
			c += tagRowSize;
		}

		pProfileTags.removeAll();
		setPaneContent(pProfileTags, boxes);

		int width, height;

		// set tags' panel width
		// JCheckBox's width = 100
		// extra = 3
		// JColorButton's width = 20
		width = boxes.length * 123 + (boxes.length - 1) * 20;

		// set tags' panel height
		if (profileTags.size() >= tagRowSize) {
			height = tagRowSize * 22;
		} else {
			height = profileTags.size() * 22;
		}
		pProfileTags.setPreferredSize(new Dimension(width, height));
		pProfileTags.setMinimumSize(pProfileTags.getPreferredSize());
		pProfileTags.setMaximumSize(pProfileTags.getPreferredSize());

//		pProfileTags.revalidate();
//		pProfileTags.repaint();
	}

	private void addProfileTag(NFCTag nfcTag) {
		getProfileTags().add(nfcTag);
		nfcTag.addToProfile(getSelectedProfile());
	}


	private void removeFromProfiles(String tagName) {
		for (int i = 0; i < cmbProfiles.getItemCount(); i++) {
			NFCProfile profile = (NFCProfile) cmbProfiles.getItemAt(i);

			ArrayList<NFCTag> tags = profile.getTags();
			for (int j = 0; j < tags.size(); j++) {
				if (tagName.toLowerCase().equals(tags.get(j).getText().toLowerCase())) {
					tags.get(j).removeFromProfile(profile);
					tags.remove(j);
					break;
				}
			}
		}
		showProfileTags();
	}


	private boolean tagError() {
		for (NFCTag nfcTag : tags) {
			if (nfcTag.getTextField().hasError()) {
				return true;
			}
		}
		return false;
	}

	private boolean exists(String tagName, ArrayList<NFCTag> tags) {
		for (NFCTag tag : tags) {
			if (tag.getText().toLowerCase().trim().equals(tagName.toLowerCase())) {
				return true;
			}
		}
		return false;
	}

	private boolean existsInProfiles(String profileName, boolean newProfile) {
		if (cmbProfiles.getItemCount() > 0) {
			for (int i = 0; i < cmbProfiles.getItemCount(); i++) {
				NFCProfile profile = (NFCProfile) cmbProfiles.getItemAt(i);

				if (i != cmbProfiles.getSelectedIndex()) {
					if (profile.getNewProfileName().equals(profileName)) {
						return true;
					}
				} else if (newProfile && profile.getProfileName().equals(profileName)) {
					return true;
				}
			}
		}
		return false;
	}


	private String getProfilePropertyName(String profile) {
		return "NFC_PROFILE_" + profile;
	}

	private NFCProfile getSelectedProfile() {
		return (NFCProfile) cmbProfiles.getSelectedItem();
	}

	private ArrayList<NFCTag> getProfileTags() {
		if (cmbProfiles.getItemCount() > 0 && cmbProfiles.getSelectedItem() != null) {
			return getSelectedProfile().getTags();
		} else {
			return new ArrayList();
		}
	}


	private void enableButtons(boolean enable) {
		frmNFCTags.enableButtons(enable);
	}


	class ProfileActionListener implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent e) {
			if (cmbProfiles.getSelectedIndex() != -1) {
				txtProfileName.setText(getSelectedProfile().getNewProfileName());
			}
			btnDeleteProfile.setEnabled(cmbProfiles.getItemCount() > 0);
			showProfileTags();
		}
	}

	class ProfileChangeListener implements DocumentListener {

		private JNonEmptyTextField textField;

		public ProfileChangeListener(JNonEmptyTextField textField) {
			this.textField = textField;
		}

		@Override
		public void insertUpdate(DocumentEvent e) {
			textChanged();
		}

		@Override
		public void removeUpdate(DocumentEvent e) {
			textChanged();
		}

		@Override
		public void changedUpdate(DocumentEvent e) {
			textChanged();
		}

		public void textChanged() {
			if (!textField.hasError() && !textField.getText().equals("")) {
				if (cmbProfiles.getItemCount() > 0) {
					if (!existsInProfiles(textField.getText().trim(), false)) {
						getSelectedProfile().setNewProfileName(textField.getText().trim());
						cmbProfiles.repaint();
					} else {
						textField.setError(true);
						SwingUtil.setTextFieldError(textField, true);
					}
				}
			}

			enableButtons(true);
		}
	}

	class DuplicateTagListener implements DocumentListener {
		@Override
		public void insertUpdate(DocumentEvent e) {
			checkText();
		}

		@Override
		public void removeUpdate(DocumentEvent e) {
			checkText();
		}

		@Override
		public void changedUpdate(DocumentEvent e) {
			checkText();
		}

		public void checkText() {
			checkDuplicates();
			showProfileTags();
		}
	}

	//TODO Create property changer listener for buttons, to activate "apply" button

	private void checkDuplicates() {
		TreeSet<String> tagTexts = new TreeSet<>();
		for (NFCTag tag : tags) {
			JNonEmptyTextField textField = tag.getTextField();
			String text = textField.getText().toLowerCase().trim();

			tag.getProfileCheckBox().setText(tag.getText());
			if (tagTexts.contains(text)) {
				SwingUtil.setTextFieldError(textField, true);
			} else {
				tagTexts.add(text);
				SwingUtil.setTextFieldError(textField, text.equals(""));
			}
		}
	}
}
